////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016-2018 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxoverridesettingsfile.h
/// @brief Declarations for the OverrideSettingsFile class.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef CAMXOVERRIDESETTINGSFILE_H
#define CAMXOVERRIDESETTINGSFILE_H

// Common CamX Includes
#include "camxhashmap.h"
#include "camxincs.h"

// Core CamX Includes
#include "camxoverridesettingsstore.h"
#include "g_camxsettings.h"

CAMX_NAMESPACE_BEGIN

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Type Definitions
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Encapsulates an entry in the cache of settings read from the file.
struct SettingCacheEntry
{
    UINT32  settingStringHash;              ///< The 32-bit setting string hash value
    CHAR    valueString[MaxStringLength];   ///< The setting value string read from the override setting text file
#if SETTINGS_DUMP_ENABLE
    CHAR    keyString[MaxStringLength];     ///< The setting key string read from the override setting text file
#endif // SETTINGS_DUMP_ENABLE
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief OverrideSettingsFile is the implementation of the IOverrideSettingsStore interface for override setting text files.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class OverrideSettingsFile final : public IOverrideSettingsStore
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Public Methods
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Create
    ///
    /// @brief  This function creates an instance of the OverrideSettingsFile class.
    ///
    /// @return An instance of the OverrideSettingsFile class
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static OverrideSettingsFile* Create();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// UpdatePropertyList
    ///
    /// @brief  Updates the properties set on the target.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE VOID UpdatePropertyList()
    {
        // First thing we need to do is enumerate all of the props on the system and figure out
        // if any camera specific ones are set and add them to the Hashmap
        OsUtils::GetPropertyList(SettingPropertyCallback, this);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Destroy
    ///
    /// @brief  This function destroys the instance of the OverrideSettingsFile class.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID Destroy();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReadSettingINT
    ///
    /// @brief  This function reads a signed integer value from the settings store.
    ///
    /// @param  stringHash  The 32-bit hash of the setting to retrieve
    /// @param  pVal        A pointer to the storage for the signed integer setting's value
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID ReadSettingINT(
        UINT32  stringHash,
        INT*    pVal
        ) const;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReadSettingUINT
    ///
    /// @brief  This function reads an unsigned integer value from the settings store.
    ///
    /// @param  stringHash  The 32-bit hash of the setting to retrieve
    /// @param  pVal        A pointer to the storage for the unsigned integer setting's value
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID ReadSettingUINT(
        UINT32  stringHash,
        UINT*   pVal
        ) const;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReadSettingBOOL
    ///
    /// @brief  This function reads a Boolean value from the settings store.
    ///
    /// @param  stringHash  The 32-bit hash of the setting to retrieve
    /// @param  pVal        A pointer to the storage for the Boolean setting's value
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID ReadSettingBOOL(
        UINT32  stringHash,
        BOOL*   pVal
        ) const;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReadSettingFLOAT
    ///
    /// @brief  This function reads a floating point value from the settings store.
    ///
    /// @param  stringHash  The 32-bit hash of the setting to retrieve
    /// @param  pVal        A pointer to the storage for the floating point setting's value
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID ReadSettingFLOAT(
        UINT32  stringHash,
        FLOAT*  pVal
        ) const;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReadSettingEnum
    ///
    /// @brief  This function reads an enumerated type value from the settings store.
    ///
    /// @param  stringHash              The 32-bit hash of the setting to retrieve
    /// @param  pVal                    A pointer to the storage for the enumerated type setting's value
    /// @param  pEnumeratorToHashMap    The array of enumerator-to-hash mappings
    /// @param  enumeratorToHashMapSize The number of elements in the enumerator-to-hash mapping array
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID ReadSettingEnum(
        UINT32                  stringHash,
        INT*                    pVal,
        EnumeratorToHashMap*    pEnumeratorToHashMap,
        UINT                    enumeratorToHashMapSize
        ) const;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ReadSettingString
    ///
    /// @brief  This function reads a string value from the settings store.
    ///
    /// @param  stringHash      The 32-bit hash of the setting to retrieve
    /// @param  pVal            A pointer to the storage for the string setting's value
    /// @param  stringLength    Then length of the string in bytes
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID ReadSettingString(
        UINT32  stringHash,
        CHAR*   pVal,
        SIZE_T  stringLength
        ) const;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsSettingOverridden
    ///
    /// @brief  Indicates whether a setting has been added to the cache, meaning that some value was explicitly set in the
    ///         override settings text file.
    ///
    /// @param  stringSettingHash The 32-bit hash of the setting to retrieve
    ///
    /// @return TRUE if setting is overridden, FALSE otherwise (indicating default value is used)
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual BOOL IsSettingOverridden(
        UINT32 stringSettingHash
        ) const;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FindOverrideSetting
    ///
    /// @brief  Searches the override settings cache for the given settings string hash and returns a pointer to the cache
    ///         entry if found.
    ///
    /// @param  settingStringHash The 32-bit hash of the setting to find
    ///
    /// @return Pointer to the cache entry if found, NULL otherwise.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE SettingCacheEntry* FindOverrideSetting(
        UINT32 settingStringHash
        ) const
    {
        CamxResult          result = CamxResultSuccess;
        VOID*               pVal = NULL;
        SettingCacheEntry*  pSettingCacheEntry = NULL;

        result = m_pOverrideSettingsCache->GetInPlace(&settingStringHash, &pVal);
        if (CamxResultSuccess == result)
        {
            pSettingCacheEntry = *(reinterpret_cast<SettingCacheEntry**>(pVal));
        }

        return pSettingCacheEntry;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AddHash
    ///
    /// @brief  Adds a given hash to the hash table cache for settings
    ///
    /// @param  settingStringHash  The 32-bit hash of the setting to add
    /// @param  pSettingCacheEntry The entry to add to the cache
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE VOID AddHash(
        UINT32             settingStringHash,
        SettingCacheEntry* pSettingCacheEntry
        ) const
    {
        m_pOverrideSettingsCache->Put(&settingStringHash, pSettingCacheEntry);
    }

#if SETTINGS_DUMP_ENABLE
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// DumpOverriddenSettings
    ///
    /// @brief  This function prints all overridden settings names and values in the settings store.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID DumpOverriddenSettings() const;
#endif // SETTINGS_DUMP_ENABLE

protected:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Protected Methods
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// OverrideSettingsFile
    ///
    /// @brief  The private constructor for the OverrideSettingsFile object.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    OverrideSettingsFile();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ~OverrideSettingsFile
    ///
    /// @brief  The private destructor for the OverrideSettingsFile object.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual ~OverrideSettingsFile();

private:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Private Methods
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Initialize
    ///
    /// @brief  Reads the override settings text file, caching all key/value pairs.
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult Initialize();

#if SETTINGS_DUMP_ENABLE
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// DumpData
    ///
    /// @brief  Free data from hashmap
    ///
    /// @param  pData pointer to val in hashmap
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static VOID DumpData(
        VOID* pData);
#endif // SETTINGS_DUMP_ENABLE

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FreeData
    ///
    /// @brief  Free data from hashmap
    ///
    /// @param  pData pointer to val in hashmap
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static VOID FreeData(
        VOID* pData)
    {
        if ((NULL != pData) && (NULL != *static_cast<VOID**>(pData)))
        {
            CAMX_FREE(*static_cast<VOID**>(pData));
            *static_cast<VOID**>(pData) = NULL;
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SettingPropertyCallback
    ///
    /// @brief  Callback function for getting the android properties with property_list
    ///
    /// @param  pKey  property key name
    /// @param  pVal  property key val
    /// @param  pData pointer of the instance of the overridesettingsfile
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static VOID SettingPropertyCallback(
        const CHAR* pKey,
        const CHAR* pVal,
        VOID* pData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetSettingsStringHashValue
    ///
    /// @brief  Creates a hash for the settings string passed in for the purpose of obfuscation. Case independent.
    ///
    /// @note   Must match GetSettingsStringHashValue() in settingsgenerator.pl
    ///
    /// @param  pSettingsString The unencrypted setting string
    ///
    /// @return The setting string hash value as a 32-bit unsigned integer
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT32 GetSettingsStringHashValue(
        const CHAR* pSettingsString);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ParseSettingInt
    ///
    /// @brief  Convert a string to an INT settings value.
    ///
    /// @param  pSettingStringVal The string to be parsed
    /// @param  pVal              Value pointer to return
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CamxResult ParseSettingInt(
        CHAR* pSettingStringVal,
        INT*  pVal);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ParseSettingUint
    ///
    /// @brief  Convert a string to an INT settings value.
    ///
    /// @param  pSettingStringVal The string to be parsed
    /// @param  pVal              Value pointer to return
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CamxResult ParseSettingUint(
        CHAR* pSettingStringVal,
        UINT* pVal);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ParseSettingBool
    ///
    /// @brief  Convert a string to an INT settings value.
    ///
    /// @param  pSettingStringVal The string to be parsed
    /// @param  pVal              Value pointer to return
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CamxResult ParseSettingBool(
        CHAR* pSettingStringVal,
        BOOL* pVal);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ParseSettingFloat
    ///
    /// @brief  Convert a string to an INT settings value.
    ///
    /// @param  pSettingStringVal The string to be parsed
    /// @param  pVal              Value pointer to return
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CamxResult ParseSettingFloat(
        CHAR*  pSettingStringVal,
        FLOAT* pVal);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ParseSettingEnum
    ///
    /// @brief  Convert a string to an INT settings value.
    ///
    /// @param  pSettingStringVal        The string to be parsed
    /// @param  pVal                     Value pointer to return
    /// @param  pEnumeratorToHashMap     Hash table pointer
    /// @param  enumeratorToHashMapSize  Size of the has table
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CamxResult ParseSettingEnum(
        CHAR*                pSettingStringVal,
        INT*                 pVal,
        EnumeratorToHashMap* pEnumeratorToHashMap,
        UINT                 enumeratorToHashMapSize);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ParseSettingString
    ///
    /// @brief  Convert a string to an INT settings value.
    ///
    /// @param  pSettingStringVal The string to be parsed
    /// @param  pVal              Value pointer to return
    /// @param  stringLength      String length
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CamxResult ParseSettingString(
        CHAR*  pSettingStringVal,
        CHAR*  pVal,
        SIZE_T stringLength);

    // Do not implement the copy constructor or assignment operator
    OverrideSettingsFile(const OverrideSettingsFile& rOverrideSettingsFile) = delete;
    OverrideSettingsFile& operator= (const OverrideSettingsFile& rRHS) = delete;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Private Member Data
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    Hashmap* m_pOverrideSettingsCache;  ///< Hashmap containing the override settings data
};

CAMX_NAMESPACE_END

#endif // CAMXOVERRIDESETTINGSFILE_H
